#include<utils.h>
QVector3D random_in_unit_sphere()
{
    QVector3D p;
    do{
        p=QVector3D(Random::get(-0.99,0.99),
                    Random::get(-0.99,0.99),
                    Random::get(-0.99,0.99));
    }while (p.length()>=1.0);
    return p;
}
QVector3D random_in_unit_disk()
{
    QVector3D p;
    do{
        p=QVector3D(Random::get(-0.99,0.99),
                    Random::get(-0.99,0.99),0);
    }while(QVector3D::dotProduct(p,p)>=1.0);
    return p;
}
QVector3D reflect(const QVector3D&v,const QVector3D&n)
{
    return v-2*QVector3D::dotProduct(v,n)*n;
}
bool refract(const QVector3D&v,const QVector3D&n,float ni_over_nt,QVector3D&refracted)
{
    QVector3D uv=v.normalized();
    float dt=QVector3D::dotProduct(uv,n);//-cos
    float discriminant=1.0-ni_over_nt*ni_over_nt*(1-dt*dt);
    if(discriminant>0)
    {
        refracted=ni_over_nt*(uv-n*dt)-n*sqrt(discriminant);
        return true;
    }
    else
    {
        return false;
    }

}
float schlick(float cosine,float ref_idx){
    float r0=(1-ref_idx)/(1+ref_idx);
    r0=r0*r0;
    return r0+(1-r0)*pow((1-cosine),5);
}

aabb surrounding_box(aabb box0, aabb box1)
{
    QVector3D small(fmin(box0.min().x(),box1.min().x()),
                    fmin(box0.min().y(),box1.min().y()),
                    fmin(box0.min().z(),box1.min().z()));
    QVector3D big(fmax(box0.max().x(),box1.max().x()),
                  fmax(box0.max().y(),box1.max().y()),
                  fmax(box0.max().z(),box1.max().z()));
    return aabb(small,big);
}

void get_sphere_uv(const QVector3D &p, float &u, float &v)
{
    float phi=atan2(p.z(),p.x());
    float theta=asin(p.y());
    u=(phi+M_PI)/(2*M_PI);
    v=(theta+M_PI_2)/M_PI;
}
